home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / xcmd / dxcmds34.sit / Dartmouth XCMD's 3.4.3 / card_16339.txt < prev    next >
Text File  |  1990-04-17  |  50KB  |  1,574 lines

  1. -- card: 16339 from stack: in.3
  2. -- bmap block id: 16385
  3. -- flags: 4000
  4. -- background id: 7836
  5. -- name: MenuHandler
  6. ----- HyperTalk script -----
  7. on openCard
  8.   global checked
  9.   put false into checked
  10.   pass openCard
  11. end openCard
  12.  
  13. on closecard
  14.   RemoveMenu
  15.   set the name of btn 1 to "Install Menu"
  16. end closecard
  17.  
  18. on InstallMenu
  19.   global ExampleMenu
  20.   put "(Disabled,Check,Test/A" into ExampleMenu
  21.   MenuHandler "Add","Example",ExampleMenu
  22.   MenuHandler "Disable","Go","Back"
  23.   answer "Disabled HyperCard's 'go Back' menu item."
  24. end InstallMenu
  25.  
  26. on RemoveMenu
  27.   MenuHandler "Delete",Example
  28.   MenuHandler "Enable","Go","Back"
  29. end RemoveMenu
  30.  
  31. on domenu anItem
  32.   global ExampleMenu, Disabled
  33.   --anItem is the name of the menu item choosen
  34.   -- HelpMenu is a list of items in my own help menu
  35.   -- Disabled is the list of items that I have disabled
  36.   if Disabled contains anItem then
  37.     answer "HyperCard menu item "&anItem&" is disabled" with "OK"
  38.     exit domenu
  39.   else if ExampleMenu contains anItem then
  40.     DoExample anItem -- see which item it is and do something
  41.   else   -- is an enable HyperCard item
  42.     pass domenu -- pass it on down the line
  43.     exit domenu
  44.   end if
  45. end domenu
  46.  
  47. on DoExample anItem
  48.   global checked
  49.   if anItem is "Check" then
  50.     if checked is not true then
  51.       MenuHandler "Mark","Example","Check",check
  52.       put true into checked
  53.     else
  54.       MenuHandler "Mark","Example","Check",none
  55.       put false into checked
  56.     end if
  57.   else if anItem is "Test" then
  58.     answer "You have chosen the Test menu item."
  59.   end if
  60. end DoExample
  61.  
  62.  
  63.  
  64. -- part 3 (button)
  65. -- low flags: 00
  66. -- high flags: A003
  67. -- rect: left=76 top=298 right=320 bottom=176
  68. -- title width / last selected line: 0
  69. -- icon id / first selected line: 0 / 0
  70. -- text alignment: 1
  71. -- font id: 0
  72. -- text size: 12
  73. -- style flags: 0
  74. -- line height: 16
  75. -- part name: Install Menu
  76. ----- HyperTalk script -----
  77. on mouseUp
  78.   global ExampleMenu
  79.   if the short name of me is "Install Menu" then
  80.     InstallMenu -- see card script
  81.     set the name of me to "Remove Menu"
  82.   else
  83.     RemoveMenu -- see card script
  84.     set the name of me to "Install Menu"
  85.   end if
  86. end mouseUp
  87.  
  88.  
  89.  
  90. -- part 5 (field)
  91. -- low flags: 01
  92. -- high flags: 2007
  93. -- rect: left=18 top=32 right=288 bottom=480
  94. -- title width / last selected line: 0
  95. -- icon id / first selected line: 0 / 0
  96. -- text alignment: 0
  97. -- font id: 3
  98. -- text size: 10
  99. -- style flags: 0
  100. -- line height: 13
  101. -- part name: Documentation
  102.  
  103.  
  104. -- part 6 (button)
  105. -- low flags: 00
  106. -- high flags: A003
  107. -- rect: left=284 top=298 right=320 bottom=453
  108. -- title width / last selected line: 0
  109. -- icon id / first selected line: 0 / 0
  110. -- text alignment: 1
  111. -- font id: 0
  112. -- text size: 12
  113. -- style flags: 0
  114. -- line height: 16
  115. -- part name: Show C Source: part 1
  116. ----- HyperTalk script -----
  117. on mouseUp
  118.   if the short name of me is "Show C Source: part 1" then
  119.     set the visible of card field "source1" to true
  120.     set the visible of card field "source2" to false
  121.     set the name of me to "Show C Source: part 2"
  122.   else if the short name of me is "Show C Source: part 2" then
  123.     set the visible of card field "source2" to true
  124.     set the visible of card field "source1" to false
  125.     set the name of me to "Hide C Source"
  126.   else
  127.     set the visible of card field "source2" to false
  128.     set the visible of card field "source1" to false
  129.     set the name of me to "Show C Source: part 1"
  130.   end if
  131. end mouseUp
  132.  
  133.  
  134.  
  135. -- part 7 (field)
  136. -- low flags: 81
  137. -- high flags: 0007
  138. -- rect: left=18 top=31 right=289 bottom=492
  139. -- title width / last selected line: 0
  140. -- icon id / first selected line: 0 / 0
  141. -- text alignment: 0
  142. -- font id: 3
  143. -- text size: 10
  144. -- style flags: 0
  145. -- line height: 13
  146. -- part name: source1
  147.  
  148.  
  149. -- part 8 (field)
  150. -- low flags: 81
  151. -- high flags: 0007
  152. -- rect: left=18 top=31 right=289 bottom=492
  153. -- title width / last selected line: 0
  154. -- icon id / first selected line: 0 / 0
  155. -- text alignment: 0
  156. -- font id: 3
  157. -- text size: 10
  158. -- style flags: 0
  159. -- line height: 13
  160. -- part name: source2
  161.  
  162.  
  163. -- part contents for card part 5
  164. ----- text -----
  165. MenuHandler version 1.2d10
  166. Roger Brown
  167.  
  168. version 1.2d7 note: interface to "show" command has changed.  See below.
  169.  
  170. MenuHandler is an XCMD that gives you the ability to add and manipulate your own menus in a HyperCard stack.  You can add and delete whole menus and items from menus. You can set and unset check marks. You can change the names of HyperCard's menus and items in them, but this is not advised because HyperCard handles its own menus in a special way.  You can, however, hide HyperCard's menus or disable items in them using some features of this XCMD. 
  171.  
  172. To use this XCMD you will have to install your own DoMenu handler and maintain some special globals. These are explained below.
  173.  
  174. Note: This version does not support hierarchical menus.
  175. Warning: Does not work with menu patches for large Radius screens.
  176.  
  177. INVOKING MENUHANDLER
  178.  
  179.   HyperCard Syntax is:
  180.    
  181.           MenuHandler opcode,title,other things according to  opcode
  182.    
  183.     it returns:     error messages
  184.    
  185.    where    the opcodes are:
  186.                         
  187.                  Add - adds a new menu
  188.                            parameters are title,item string,before 
  189.                            title is the menu title
  190.                            items is string containing the menu items and their
  191.                                   states in the normal Mac ToolBox format except 
  192.                                   for commas instead of semi-colons to make 
  193.                                   hypertalk level processing easier
  194.                            before is a string that names a menu to insert this
  195.                                   one before (if empty, this menu goes at the
  196.                                   end of the menu bar)
  197.                 Delete - deletes a menu and its handle
  198.                            parameter is title
  199.                 Hide - hides a menu but remembers it for later restoration
  200.                            parameter is title
  201.                 Show - restores a hidden menu
  202.                            parameter is title,beforeMenu (used to be afterMenu)
  203.                            where after menu can be specified or the default is
  204.                            after all menus (used to be its original position, but it never worked)
  205.                 Insert - inserts a menu item
  206.                           parameters are menu title, item name with format
  207.                           specifications, after item (number or name)
  208.                 Remove - removes a menu item
  209.                           parameters are menu title, item name or number
  210.                 Enable - enables a menu item
  211.                           parameters are menu title, item name or number
  212.                           A number of 0 enables the whole menu
  213.                 Disable - disables a menu item
  214.                          parameters are menu title, item name or number
  215.                          A number of 0 disables the whole menu
  216.                 Mark - checks an item
  217.                          parameters are menu title, item name or number
  218.                          and mark: none,command,check,diamond, or apple
  219.                                                            
  220.       To compile: create a project with this and MacTraps. Build as code       
  221.                           resource type XCMD named MenuHandler.
  222.  
  223. EXAMPLE
  224.  
  225.  ex.  MenuHandler "Add","Help","Introduction,(----,Glossary"
  226.   
  227. SPECIAL GLOBALS
  228.  
  229.       A HyperCard global is maintained for every menu added through
  230.       MenuHandler. The global has the same name as the menu.
  231.       The menu items in a menu are found in a HyperCard item list
  232.       contained in a  global whose name is the name of the menu
  233.       concatenated with the word "Menu" . This makes it 
  234.       easy to test if a  doMenu call is for an added menu.
  235.       
  236.        ex. global HelpMenu = "Introduction,Getting Started,Glossary"
  237.       
  238.       An extra global is maintained that includes a list of all items
  239.       that are currently disabled. These can be in new menus or in
  240.       HyperCard's menus. This list is needed because some HyperCard
  241.       menu actions can still proceed even when their menu items appear
  242.       to be disabled.   
  243.  
  244. DOMENU HANDLER
  245.  
  246.       To use MenuHandler, you need to have your own DoMenu       
  247.       handler to see if the menu action is one of your own.  If it isn't
  248.       then you pass it on to HyperCard.  Another reason to have your
  249.       own DoMenu handler is to catch HyperCard menu items that you
  250.       want to be disabled because HyperCard doesn't pay any attention
  251.       to you if you make one of its items look disabled.  A sample
  252.       DoMenu handler is shown here and another is in the script of this
  253.       stack.
  254.  
  255.       example:
  256.  
  257.       on domenu anItem
  258.          global HelpMenu, Disabled
  259.          --anItem is the name of the menu item chosen
  260.          -- HelpMenu is a list of items in my own help menu
  261.          -- Disabled is the list of items that I have disabled
  262.          if Disabled contains anItem then
  263.            answer "HyperCard menu item "&anItem&" is disabled"┬¼
  264.            with "OK"
  265.            exit domenu
  266.          else if HelpMenu contains anItem then
  267.              DoMyHelp anItem -- see which item it is and do something
  268.          else   -- is an enable HyperCard item
  269.              pass domenu - pass it on down the line 
  270.              exit domenu
  271.         end if
  272.      end domenu
  273.  
  274. REVISION HISTORY
  275. 1.2d3 first public release version
  276. 1.2d4 fix problem with empty item list in AddAMenu
  277. 1.2d6 allow arbitrarily long menus in AddAMenu and InsertMenuItem
  278. 1.2d7 Fixed positioning problem in "show" command that never worked correctly.
  279.            Compiled under THINK CΓäó v.4.0
  280. 1.2d10 2/21/90 fixed bug in "insert" operation that put new items 2 slots below  
  281.            desired location in the item list.
  282.  
  283.  
  284. -- part contents for card part 7
  285. ----- text -----
  286. /* MenuHandler1.2d10.c */
  287. /* ┬⌐ Digital Medicine Inc. 1988 */
  288. /* written in THINK CΓäó 4.0  ┬⌐ Think Technologies, Inc */
  289. /* by Roger Brown 7/21/88  Courseware Development group */
  290.  
  291. /* version 1.2d10 fixes a bug in the "insert" option that put items 2 slots below the  
  292.    specified item in the item list.
  293. /* version 1.2d8 and 1.2d9 included popup menus but that functionality has moved to the  
  294.   PopList XFCN.
  295. /* 9/1/89 version 1.2d7: compiled under THINK CΓäó 4.0, working on "show" position bug */
  296. /* had to redefine the "show mnu" interface to have a beforeMenu parameter with
  297.    a default of "at the end". Numbr input is not allowed. It never worked anyway.
  298.    We clear out all references to me position of the menu when showing and hidding
  299.    because it has no significance anyway. */
  300. /* 5/5/89 version 1.2d6: Now handles arbitrarily long menu item lists in AddAMenu 
  301.    and InsertMenuItem. */
  302. /* version 1.2d4 will bomb if you insert enough items to make the item list global
  303.    greater than 255 chars.  The Menu Manager dosen't care, just my UpdateItemGlobal
  304.    procedure. */
  305. /* 5/5/89 version 1.2d4: fix empty list problem in AddAMenu */
  306. /* This is a HyperCard XFCN that handles menus in all sorts of ways.
  307.   
  308.   *********************************
  309.   *** Requires HC v1.2 or later *** 
  310.   *********************************
  311.   
  312.   HyperCards Syntax is:
  313.    
  314.                 MenuHandler message,title,other things according to message
  315.    
  316.    ex.  MenuHandler "Add","Help","Introduction,(----,Glossary"
  317.   
  318.    returns:     error messages
  319.    
  320.    where    message is one of these opcodes:
  321.                                 Add - adds a new menu
  322.                                         parameters are title,item string,before 
  323.                                         title is the menu title
  324.                         items is string containing the menu items and their
  325.                                   states in the normal Mac ToolBox format except 
  326.                                   for commas instead of semi-colons to make 
  327.                                   hypertalk level processing easier
  328.                         before is a string that names a menu to insert this
  329.                                   one before (if empty, this menu goes at the
  330.                                   end of the menu bar)
  331.                 Delete - deletes a menu and its handle
  332.                      parameter is title
  333.                 Hide - hides a menu but remembers it for later restoration
  334.                      parameter is title
  335.                 Show - restores a hidden menu
  336.                      parameter is title,beforeMenu
  337.                      where after menu can be specified or the default is
  338.                      after all menus
  339.                 Insert - inserts a menu item
  340.                      parameters are menu title, item name with format
  341.                      specifications, after item (number or name)
  342.                 Remove - removes a menu item
  343.                      parameters are menu title, item name or number
  344.                 Enable - enables a menu item
  345.                      parameters are menu title, item name or number
  346.                      A number of 0 enables the whole menu
  347.                 Disable - disables a menu item
  348.                          parameters are menu title, item name or number
  349.                      A number of 0 disables the whole menu
  350.                 Mark - checks an item
  351.                      parameters are menu title, item name or number
  352.                      and mark: none,command,check,diamond, or apple
  353.                              
  354.          
  355.       A HyperCard global is maintained for every menu added through
  356.       MenuHandler. The menu items in a menu are found in a HyerCard item
  357.       list in the global with the menu's name. This makes it easy to 
  358.       test if a doMenu call is for an added menu.
  359.       
  360.       ex. global HelpMenu = "Introduction,Getting Started,Glossary"
  361.       
  362.       An extra global is maintained that includes a list of all items
  363.       that are currently disabled. These can be in new menus or in
  364.       HyperCard's menus. This list is needed because some HyperCard
  365.       menu actions can still proceed even when their menu items appear
  366.       to be disabled.   
  367.                          
  368.       To compile: create a project with this, ANSI-A4 and MacTraps. Build as code 
  369.       resource type XFCN named MenuHandler.
  370. */
  371.  
  372. #include "MenuMgr.h"
  373. #include "HyperXCmd.h"
  374. #include "XCmdGlue.inc.c"
  375. #include "SetUpA4.h"
  376.  
  377. #define FALSE 0
  378. #define TRUE !FALSE
  379. #define NULL 0L
  380.  
  381. typedef struct MenuRec {
  382.         MenuHandle menuOH;
  383.         int menuLeft;
  384. } MenuRec;
  385.  
  386. typedef struct DynamicMenuList {   /* this is actually a dynamic structure */
  387.         int lastMenu;
  388.         int lastRight;
  389.         int mbResID;
  390.         MenuRec menu[64];    /* 64 is an aribtrary number, but plenty big */
  391. } DynamicMenuList,*DMLPtr,**DMLHandle;
  392.  
  393. char isNumber();
  394. long ItemNumber();
  395. MenuHandle GetHiddenMenu();
  396.  
  397. /* build a return result structure from a string */
  398.  
  399. ResultIs(paramPtr,theResult)
  400. XCmdBlockPtr    paramPtr;
  401. char *theResult;
  402. {
  403.         long len;
  404.         Handle resultHandle;
  405.         len = 1+strlen(theResult);
  406.         resultHandle = NewHandle(len);
  407.         BlockMove(theResult,*resultHandle,len);
  408.         paramPtr->returnValue = resultHandle;
  409. }
  410.  
  411. /* change a string into its upper case equivalent */
  412.  
  413. ucase(s)
  414. char *s;
  415. {
  416.         int i;
  417.         char c;
  418.         
  419.         for (i=0;i<strlen(s);i++) {
  420.                 s[i] = toupper(s[i]);
  421.         }
  422. }
  423.  
  424. /* Get the number of HyperCard comma delimited items in string s. */
  425.  
  426. int NumHCItems(s)
  427. char *s;
  428. {
  429.         int c,len,count,j;
  430.         char temp[255];
  431.         long it;
  432.         
  433.         count = j = 0;
  434.         len = strlen(s);
  435.         for (c=0;c<len;c++) {
  436.                 if (s[c]==',') {
  437.                         count = count + 1;
  438.                         j = 0;
  439.                 }
  440.                 else {
  441.                         temp[j] = s[c];
  442.                         j++;
  443.                         if (c==(len-1)) { /* last item, no comma */
  444.                                 count = count+1;
  445.                                 break;
  446.                         }
  447.                 }
  448.         }
  449.         return count;
  450. }
  451.  
  452. /* Get the number of HyperCard lines in string s. */
  453.  
  454. NumHCLines(source) 
  455. char *source;
  456. {
  457.         int i,c,len;
  458.         
  459.         len = strlen(source);
  460.         c = 0;
  461.         for (i=0;i<len;i++) {          
  462.                 if (source[i]==13) c++;
  463.         }
  464.         if (source[i-1]!=13) c++;          /* last line might not have CR */
  465.         return c;
  466. }
  467.  
  468. /* Get HyperCard comma delimited item i from item list string inStr. 
  469.    Return it in outStr */
  470.  
  471. GetHCItem(inStr,i,outStr)
  472. char *inStr,*outStr;
  473. int i;
  474. {
  475.         int c,len,count,j;
  476.         char temp[255];
  477.         
  478.         count = j = 0;
  479.         len = strlen(inStr);
  480.         for (c=0;c<len;c++) {
  481.                 if (inStr[c]==',') {
  482.                         count = count + 1;
  483.                         if (count==i) break;
  484.                         j = 0;
  485.                 }
  486.                 else {
  487.                         temp[j] = inStr[c];
  488.                         j++;
  489.                         if (c==(len-1)) { /* last item, no comma */
  490.                                 count = count+1;
  491.                                 break;
  492.                         }
  493.                 }
  494.         }
  495.         if (count < i) strcpy(temp,"");  /* no item there */
  496.         temp[j] = 0;
  497.         strcpy(outStr,temp);
  498.         return;
  499. }
  500.  
  501. /* get line number 'line' from source and return in dest */
  502.  
  503. GetHCLine(line,source,dest)
  504. int line;
  505. char *source,*dest;
  506. {
  507.         int i,j,c,len;
  508.  
  509.         len = strlen(source);
  510.         c = 1;
  511.         i = 0;
  512.         while (c<line) {
  513.                 if (source[i]==13) c++;
  514.                 i++;
  515.                 if (i>len) {     /* out of range */
  516.                         strcpy(dest,"");
  517.                         return;
  518.                 }
  519.         }
  520.         c = 0;
  521.         for (j=i;j<len;j++) {
  522.                 *(dest+c) = source[j];
  523.                 if (source[j]==13) break;    /* line ended */
  524.                 c++;
  525.         }
  526.         *(dest+c) = (char)0;
  527. }
  528.  
  529. /* Test if item in itemStr is in container */
  530.  
  531. ItemInContainer(itemStr,container)
  532. char *itemStr,*container;
  533. {
  534.         int c,len,j;
  535.         char temp[255];
  536.         
  537.         j = 0;
  538.         len = strlen(container);
  539.         for (c=0;c<len;c++) {
  540.                 if (container[c]==',') {
  541.                         if (strcmp(itemStr,temp)==0) return TRUE;
  542.                         j = 0;
  543.                 }
  544.                 else {
  545.                         temp[j] = container[c];
  546.                         j++;
  547.                         temp[j] = 0;
  548.                         if (c==(len-1)) { /* last item, no comma */
  549.                                 break;
  550.                         }
  551.                 }
  552.         }
  553.         temp[j] = 0;
  554.         if (strcmp(itemStr,temp)==0) return TRUE;
  555.         return FALSE;
  556.  
  557. }
  558.  
  559. /* return false if s is not a valid integer, true and number if it is */
  560.  
  561. char isNumber(s,num)
  562. char *s;
  563. long *num;
  564. {
  565.         /* s enters and exits in C format */
  566.         Str255 temp;
  567.         int i,len;
  568.         
  569.         /* see if all characters are digits */
  570.         len = strlen(s);
  571.         for (i=0;i<len;i++) {
  572.                 if (!isdigit(s[i])) return FALSE;
  573.         }
  574.         CtoPstr((char *)s);
  575.         StringToNum(s,num);
  576.         PtoCstr((char *)s);
  577.         return TRUE; 
  578. }
  579.  
  580.  
  581. /* Get the id of menu with title name. */
  582.    
  583. GetMenuID(name)
  584. char *name;
  585. {
  586.         DMLHandle theList;
  587.         int lastMenu,i,j,numMenus;
  588.         MenuRec anEntry;
  589.         MenuHandle MHandle;
  590.         Ptr MPtr;
  591.         int *idPtr;
  592.         Str255 title,uName;
  593.         char len;
  594.                 
  595.                 
  596.         strcpy(uName,name);     /* copy name and change it to upper case */
  597.         ucase(name);
  598.         theList = (DMLHandle)GetMenuBar();   /* get the menu list */
  599.         HLock((Handle)theList);
  600.         lastMenu = (**theList).lastMenu;
  601.         numMenus = lastMenu/6;
  602.         for (i=0;i<numMenus;i++) {            /* look at each menu in the list */
  603.                 anEntry = (**theList).menu[i];
  604.                 MHandle = anEntry.menuOH;
  605.                 MPtr = (Ptr)*MHandle;
  606.                 len = *(MPtr+14);
  607.                 for (j=0;j<len;j++) {             /* get its title */
  608.                         title[j] = *(MPtr+15+j);
  609.                 }
  610.                 title[j] = 0;
  611.                 ucase(title);
  612.                 if (strcmp(title,name)==0){        /* is it the same as name? */
  613.                         idPtr = (int*)MPtr;
  614.                         HUnlock(theList);
  615.                         return *idPtr;                 /* return its id  */
  616.                 }
  617.         }
  618.         HUnlock(theList);
  619.         return 0;                              /* not found */
  620. }
  621.  
  622. /* get item number of an item, given its name */
  623.  
  624. long ItemNumber(theMenu,theItem)
  625. MenuHandle theMenu;
  626. char *theItem;
  627. {
  628.         int i,num;
  629.         Str255 temp;
  630.         
  631.         ucase(theItem);
  632.         num = 1+CountMItems(theMenu);
  633.         for (i=1;i<num;i++) {               /* scan all items in the menu */
  634.                 GetItem(theMenu,i,temp);
  635.                 ucase(temp);
  636.                 PtoCstr((char *)temp);
  637.                 if (strcmp(temp,theItem)==0)     /* found it */
  638.                         return (long)i;
  639.         }
  640.         return (long)0;                    /* not found */
  641. }
  642.  
  643.  
  644. /* Make the menus item list global agree with the menu. This completely
  645.    rebuilds the global. */
  646.  
  647. UpdateItemGlobal(paramPtr,title)
  648. XCmdBlockPtr    paramPtr;
  649. char *title;
  650. {
  651.         #define kBlockSize 255
  652.         Str255 name,temp;
  653.         int menuID,i,num;
  654.         MenuHandle theMenu;
  655.         long dummy,len;
  656.         Handle theList;
  657.         
  658.         menuID = GetMenuID(title,&dummy);
  659.         theMenu = GetMHandle(menuID);
  660.         strcpy(name,title);
  661.         strcat(name,"Menu");
  662.         CtoPstr((char *)name);
  663.         theList = NewHandle(kBlockSize);
  664.         if (theList == NULL) {
  665.                 ResultIs(paramPtr,"Out of memory in MenuHandler XCMD");
  666.                 return;
  667.         }
  668.         HLock(theList);
  669.         **theList = 0;
  670.         len = kBlockSize;
  671.         
  672.         /* scan the menu list and pick up all item names */
  673.         
  674.         num = 1+CountMItems(theMenu);
  675.         for (i=1;i<num;i++) {
  676.                 GetItem(theMenu,i,temp);
  677.                 ucase(temp);
  678.                 PtoCstr((char *)temp);
  679.                 if (strlen(*theList)+strlen(temp) > len) {   /* open up the list global */
  680.                         len = len + kBlockSize;
  681.                         HUnlock(theList);
  682.                         SetHandleSize(theList,len);
  683.                         if (MemError()!=noErr) {
  684.                                 ResultIs(paramPtr,"Out of memory in MenuHandler XCMD");
  685.                                 DisposHandle(theList);
  686.                                 return;
  687.                         }
  688.                         HLock(theList);
  689.                 }
  690.                 strcat(*theList,temp);
  691.                 if (i<num-1) strcat(*theList,",");
  692.         }
  693.         
  694.         SetGlobal(paramPtr,name,theList);
  695.         DisposHandle(theList);
  696. }
  697.  
  698.  
  699. /* remove a menu from the disable global */
  700.  
  701. RemoveFromDisableGlobal(paramPtr,theMenu,theItem)
  702. XCmdBlockPtr    paramPtr;
  703. MenuHandle theMenu;
  704. int theItem;
  705. {
  706.         Handle theGlobal,theNewGlobal;
  707.         int i,numItems;
  708.         Str255 temp,itemName,handleStr;
  709.         long len,tempLong;
  710.                 
  711.         GetItem(theMenu,theItem,itemName);
  712.         
  713.         PtoCstr((char *)itemName);
  714.         theGlobal = GetGlobal(paramPtr,"\pdisabled");
  715.         theNewGlobal = NewHandle(1);
  716.         if (MemError()!=noErr) {
  717.                 ResultIs(paramPtr,"Out of Memory");
  718.                 return;
  719.         }
  720.         MoveHHi(theGlobal);
  721.         HLock(theGlobal);
  722.         (**theNewGlobal) = 0;
  723.         MoveHHi(theNewGlobal);
  724.         HLock(theNewGlobal);
  725.         strcpy(*theNewGlobal,"");
  726.         
  727.         /* scan the current global and rebuild  with everything but this one */
  728.         
  729.         numItems = NumHCItems(*theGlobal);
  730.         for (i=0;i<numItems;i++) {
  731.                 GetHCItem(*theGlobal,i+1,temp);
  732.                  if (strcmp(itemName,temp)!=0) {   /* not this one, put it back */
  733.                         strcat(temp,",");
  734.                         len = GetHandleSize(theNewGlobal);
  735.                         len = len + (long)strlen(temp);
  736.                         HUnlock(theNewGlobal);
  737.                         SetHandleSize(theNewGlobal,len);
  738.                         if (MemError()!=noErr) {
  739.                                 ResultIs(paramPtr,"Out of Memory");
  740.                                 return;
  741.                         }
  742.                         HLock(theNewGlobal);
  743.                         /* check for errors? */
  744.                         strcat(*theNewGlobal,temp);
  745.                 }
  746.         }
  747.         
  748.         /* set the new global value */
  749.         
  750.         SetGlobal(paramPtr,"\pdisabled",theNewGlobal);
  751.         HUnlock(theGlobal);
  752.         HUnlock(theNewGlobal);
  753.         DisposHandle(theGlobal);
  754.         DisposHandle(theNewGlobal);
  755. }
  756.  
  757. /* add a menu to the disable global */
  758.  
  759. AddToDisableGlobal(paramPtr,theMenu,theItem)
  760. XCmdBlockPtr    paramPtr;
  761. MenuHandle theMenu;
  762. int theItem;
  763. {
  764.         Handle theGlobal;
  765.         Str255 numStr,temp,itemName;
  766.         long len,tempLong;
  767.  
  768.         GetItem(theMenu,theItem,itemName);
  769.         PtoCstr((char *)itemName);
  770.         theGlobal = GetGlobal(paramPtr,"\pdisabled");
  771.         HLock(theGlobal);
  772.         
  773.         /* see if its already there */
  774.         
  775.         if (ItemInContainer(itemName,*theGlobal)) {   /* already stored */
  776.                 HUnlock(theGlobal);
  777.                 DisposHandle(theGlobal);
  778.                 return;
  779.         }
  780.         
  781.         /* tack it on the end */
  782.         len = GetHandleSize(theGlobal);
  783.         len = len + (long)strlen(itemName) + 2;
  784.         HUnlock(theGlobal);
  785.         SetHandleSize(theGlobal,len);
  786.         if (MemError()!=noErr) {
  787.                 ResultIs(paramPtr,"Out of Memory");
  788.                 DisposHandle(theGlobal);
  789.                 return;
  790.         }
  791.         HLock(theGlobal);
  792.         strcat(*theGlobal,itemName);
  793.         strcat(*theGlobal,",");
  794.         HUnlock(theGlobal);
  795.         SetGlobal(paramPtr,"\pdisabled",theGlobal);
  796.         DisposHandle(theGlobal);
  797. }
  798.  
  799.  
  800. /* add a menu to the menu bar */
  801.  
  802. pascal void AddAMenu(paramPtr)
  803. XCmdBlockPtr    paramPtr;
  804. {   
  805.         int i,itsID,itemCount;
  806.         Str255 titleStr,itemStr,beforeStr;
  807.         Ptr theTitle,theItems;
  808.         MenuHandle theMenu;
  809.         int theMenuID,beforeID;
  810.         
  811.         /* check parameter count */
  812.         
  813.         if (paramPtr->paramCount < 3) {
  814.                 ResultIs(paramPtr,"Not enough parameters in Add.");
  815.                 return;
  816.         }
  817.  
  818.         /* lock down the parameters so we can point to them */
  819.         
  820.         for (i=1;i<paramPtr->paramCount;i++) {
  821.                 MoveHHi(paramPtr->params[i]);
  822.                 HLock (paramPtr->params[i]);
  823.         }
  824.         
  825.         /* get the parameters */
  826.         
  827.         theTitle = *(paramPtr->params[1]);
  828.         theItems = *(paramPtr->params[2]);
  829.         strcpy(titleStr,theTitle);
  830.                 
  831.         /* see if we really need to do this */
  832.         
  833.         if (GetMenuID(theTitle)!=0) {
  834.                 ResultIs(paramPtr,"Menu already shown.");
  835.                 for (i=1;i<paramPtr->paramCount;i++) 
  836.                         HUnlock (paramPtr->params[i]);
  837.                 return;
  838.         }
  839.         
  840.         /* get ready to talk to the menu manager */
  841.         
  842.         CtoPstr((char *)titleStr);
  843.         
  844.         /* get an id for this menu */
  845.         
  846.         itsID = 0;
  847.         while (itsID<128)
  848.                 itsID = UniqueID('MENU');
  849.                 
  850.         /* create the menu and insert the items */
  851.         
  852.         theMenu = NewMenu(itsID,titleStr);
  853.         strcpy(itemStr," ");            /* create menu with 1 blank item cuz AppendMenu */
  854.         CtoPstr((char*)itemStr);
  855.         AppendMenu(theMenu,itemStr);    /* can't handle a null string */
  856.         DelMenuItem(theMenu,1);         /* now get rid of the blank menu item */
  857.  
  858.         /* add all items by inserting - so we aren't constrained to 255 char limit */
  859.         itemCount = NumHCItems(theItems);
  860.         for (i=0;i<itemCount;i++) {
  861.                 GetHCItem(theItems,i+1,itemStr);
  862.                 CtoPstr((char *)itemStr);
  863.                 InsMenuItem(theMenu,itemStr,i+2);
  864.         }
  865.  
  866.         /* insert it as requested */
  867.         
  868.         beforeID = 0;
  869.         if (paramPtr->paramCount > 3) {
  870.                 strcpy(beforeStr,*(paramPtr->params[3]));
  871.                 beforeID = GetMenuID(beforeStr);
  872.         }
  873.         InsertMenu(theMenu,beforeID);
  874.         
  875.         /* update the menu bar */
  876.         
  877.         DrawMenuBar();
  878.         
  879.         /* create the menu global */
  880.         
  881.         PtoCstr((char *)titleStr);
  882.         UpdateItemGlobal(paramPtr,titleStr);
  883.  
  884.         /* clean up */
  885.         
  886.         for (i=1;i<paramPtr->paramCount;i++) HUnlock (paramPtr->params[i]);
  887.         
  888.         return;
  889. }
  890.  
  891. /* delete a menu from the menu bar and remove it from memory */
  892.  
  893. pascal void DeleteAMenu(paramPtr)
  894. XCmdBlockPtr    paramPtr;
  895. {   
  896.         int i,itsID;
  897.         Str255 titleStr,itemStr;
  898.         Ptr theTitle,theItems;
  899.         MenuHandle theMenu;
  900.         int theMenuID;
  901.         Handle empty;
  902.         
  903.         /* check parameter count */
  904.         
  905.         if (paramPtr->paramCount < 2) {
  906.                 ResultIs(paramPtr,"Not enough parameters in Delete.");
  907.                 return;
  908.         }
  909.  
  910.         /* lock parameters down so we can point to them */
  911.         
  912.         MoveHHi(paramPtr->params[1]);
  913.         HLock (paramPtr->params[1]);
  914.         
  915.         theTitle = *(paramPtr->params[1]);
  916.         strcpy(titleStr,theTitle);
  917.         
  918.         /* get the id of this menu */
  919.         
  920.         theMenuID = GetMenuID(titleStr);
  921.         if (theMenuID==NULL) {
  922.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu to delete");
  923.                 }
  924.         else {
  925.                 /* get the menu and do the delete */
  926.                 
  927.                 theMenu = GetMHandle(theMenuID);
  928.                         
  929.                 /* delete it from out save list if it is there */
  930.                 
  931.                 RemoveFromSaveList(paramPtr,theMenu);
  932.                 
  933.                 /* remove its items from the disabled list */
  934.                 
  935.                 for (i=0;i<CountMItems(theMenu);i++) 
  936.                         RemoveFromDisableGlobal(paramPtr,theMenu,i+1);
  937.                 
  938.                 DeleteMenu(theMenuID);
  939.                 DisposeMenu(theMenu);
  940.                 DrawMenuBar();
  941.                 
  942.                 /* clear the global with its name */
  943.                 CtoPstr((char *)titleStr);
  944.                 empty = NewHandle(1);
  945.                 if (MemError()!=noErr) {
  946.                         ResultIs(paramPtr,"Out of Memory");
  947.                         return;
  948.                 }
  949.                 HLock(empty);
  950.                 (**empty) = 0;
  951.                 HUnlock(empty);
  952.                 SetGlobal(paramPtr,titleStr,empty);
  953.                 DisposHandle(empty);
  954.         }
  955.         HUnlock (paramPtr->params[1]);
  956.         
  957.         return;
  958. }
  959.  
  960. /* store a menu title and id in a hidden HyperCard global */
  961.  
  962. StoreHiddenMenu(paramPtr,title,theMenu)
  963. XCmdBlockPtr    paramPtr;
  964. char *title;
  965. MenuHandle theMenu;
  966. {
  967.         Handle theGlobal;
  968.         Str255 numStr,temp;
  969.         long len,tempLong;
  970.         
  971.         if (GetHiddenMenu(paramPtr,title,&tempLong)!=NULL) {
  972.                 return;   /* already stored */
  973.         }
  974.         theGlobal = GetGlobal(paramPtr,"\pXXMHLISTXX");
  975.         HLock(theGlobal);
  976.         NumToString(theMenu,numStr);           /* the menu handle */
  977.         PtoCstr((char *)numStr);
  978.         strcpy(temp,title);                    /* the menu title */
  979.         strcat(temp,",");
  980.         strcat(temp,numStr);
  981.         strcat(temp,"\15");                  /* make it a HyperCard line */
  982.         
  983.         /* add it to the end of the existing global */
  984.         
  985.         len = GetHandleSize(theGlobal) + (long)strlen(temp) + 1;
  986.         HUnlock(theGlobal);
  987.         SetHandleSize(theGlobal,len);
  988.         if (MemError()!=noErr) {
  989.                 ResultIs(paramPtr,"Out of Memory");
  990.                 DisposHandle(theGlobal);
  991.                 return;
  992.         }
  993.         HLock(theGlobal);
  994.         strcat(*theGlobal,temp);
  995.         HUnlock(theGlobal);
  996.         SetGlobal(paramPtr,"\pXXMHLISTXX",theGlobal);
  997.         DisposHandle(theGlobal);
  998. }
  999.  
  1000.  
  1001. /* get a hidden menu's id from the hidden HC global. Return its handle. */
  1002.  
  1003. MenuHandle GetHiddenMenu(paramPtr,title)
  1004. XCmdBlockPtr    paramPtr;
  1005. char *title;
  1006. {
  1007.         Handle theGlobal;
  1008.         MenuHandle theMenu;
  1009.         int i,numLines;
  1010.         Str255 temp,name,idStr;
  1011.         
  1012.         /* get the hidden menu list */
  1013.         
  1014.         theGlobal = GetGlobal(paramPtr,"\pXXMHLISTXX");
  1015.         HLock(theGlobal);
  1016.         numLines = NumHCLines(*theGlobal);
  1017.         
  1018.         /* find it in the list */
  1019.         
  1020.         for (i=0;i<numLines;i++) {
  1021.                 GetHCLine(i+1,*theGlobal,temp); /* get the line for this menu */
  1022.                 GetHCItem(temp,1,name);
  1023.          if (strcmp(name,title)==0) {
  1024.                         GetHCItem(temp,2,idStr);    /* get its handle */
  1025.                         CtoPstr((char *)idStr);
  1026.                         StringToNum(idStr,&theMenu);
  1027.                         HUnlock(theGlobal);
  1028.                         DisposHandle(theGlobal);
  1029.                         return theMenu;
  1030.                 }
  1031.         }
  1032.         HUnlock(theGlobal);
  1033.         DisposHandle(theGlobal);
  1034.         return NULL;
  1035. }
  1036.  
  1037. /* remove a menu from the list of saved menus */
  1038.  
  1039. RemoveFromSaveList(paramPtr,itsHandle)
  1040. XCmdBlockPtr    paramPtr;
  1041. Handle itsHandle;
  1042. {
  1043.         Handle theGlobal,theNewGlobal;
  1044.         MenuHandle theMenu;
  1045.         int i,numLines;
  1046.         Str255 temp,itemStr,handleStr;
  1047.         long len;
  1048.         
  1049.         /* scan the global and rebuild with all parts except this one */
  1050.         
  1051.         theGlobal = GetGlobal(paramPtr,"\pXXMHLISTXX");
  1052.         theNewGlobal = NewHandle(1);
  1053.         if (MemError()!=noErr) {
  1054.                 ResultIs(paramPtr,"Out of Memory");
  1055.                 return;
  1056.         }
  1057.         HLock(theGlobal);
  1058.         HLock(theNewGlobal);
  1059.         strcpy(*theNewGlobal,"");
  1060.         NumToString((long)itsHandle,handleStr);
  1061.         PtoCstr((char *)handleStr);
  1062.         numLines = NumHCLines(*theGlobal);
  1063.         for (i=0;i<numLines;i++) {
  1064.                 GetHCLine(i+1,*theGlobal,temp);
  1065.                 GetHCItem(temp,2,itemStr);
  1066.                  if (strcmp(itemStr,handleStr)!=0) {  /* not this one, put it back */
  1067.                 strcat(temp,"\15");
  1068.                         len = GetHandleSize(theNewGlobal) + (long)strlen(temp);
  1069.                         HUnlock(theNewGlobal);
  1070.                         SetHandleSize(theNewGlobal,len);
  1071.                         HLock(theNewGlobal);
  1072.                         /* check for errors? */
  1073.                         strcat(*theNewGlobal,temp);
  1074.                 }
  1075.         }
  1076.         SetGlobal(paramPtr,"\pXXMHLISTXX",theNewGlobal);
  1077.         HUnlock(theGlobal);
  1078.         HUnlock(theNewGlobal);
  1079.         DisposHandle(theGlobal);
  1080.         DisposHandle(theNewGlobal);
  1081. }
  1082.  
  1083.  
  1084.  
  1085.  
  1086. -- part contents for card part 8
  1087. ----- text -----
  1088. /* MenuHandler source: part 2 */
  1089.  
  1090.  
  1091. /* hide a menu but save it for later restoration */
  1092. /* store info in a special hypercard global */
  1093.  
  1094. pascal void HideMenu(paramPtr)
  1095. XCmdBlockPtr    paramPtr;
  1096. {   
  1097.         int i,itsID;
  1098.         Str255 titleStr,itemStr;
  1099.         Ptr theTitle,theItems;
  1100.         MenuHandle theMenu;
  1101.         int theMenuID;
  1102.         
  1103.         /* check parameter count */
  1104.         
  1105.         if (paramPtr->paramCount < 2) {
  1106.                 ResultIs(paramPtr,"Not enough parameters in Hide.");
  1107.                 return;
  1108.         }
  1109.  
  1110.         /* lock the parameters down so we can point to them */
  1111.         
  1112.         MoveHHi(paramPtr->params[1]);
  1113.         HLock (paramPtr->params[1]);
  1114.         
  1115.         theTitle = *(paramPtr->params[1]);
  1116.         strcpy(titleStr,theTitle);
  1117.         theMenuID = GetMenuID(titleStr);
  1118.         if (theMenuID==NULL) 
  1119.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu to hide");
  1120.         else {
  1121.                 /* delete the menu from the menu list but remember its name and
  1122.                    handle */
  1123.                    
  1124.                 theMenu = GetMHandle(theMenuID);
  1125.                 DeleteMenu(theMenuID);
  1126.                 StoreHiddenMenu(paramPtr,titleStr,theMenu);
  1127.                 DrawMenuBar();
  1128.         }
  1129.         HUnlock (paramPtr->params[1]);
  1130.         
  1131.         return;
  1132. }
  1133.  
  1134. /* show a hidden menu */
  1135.  
  1136. pascal void ShowMenu(paramPtr)
  1137. XCmdBlockPtr    paramPtr;
  1138. {   
  1139.         int i,tempInt;
  1140.         Str255 titleStr,itemStr,beforeStr;
  1141.         Ptr theTitle;
  1142.         MenuHandle theMenu;
  1143.         int beforeMenuID;
  1144.         
  1145.         /* check parameter count */
  1146.         
  1147.         if (paramPtr->paramCount < 2) {
  1148.                 ResultIs(paramPtr,"Not enough parameters in Show.");
  1149.                 return;
  1150.         }
  1151.  
  1152.         /* lock parameters down so we can point to them */
  1153.         
  1154.         for (i=1;i<paramPtr->paramCount;i++) {
  1155.                 MoveHHi(paramPtr->params[i]);
  1156.                 HLock (paramPtr->params[i]);
  1157.         }
  1158.         
  1159.         theTitle = *(paramPtr->params[1]);
  1160.         strcpy(titleStr,theTitle);
  1161.         ucase(titleStr);
  1162.         beforeStr[0] = 0;
  1163.         if (paramPtr->paramCount>2)
  1164.                 strcpy(beforeStr,*paramPtr->params[2]);
  1165.         
  1166.         /* find the menu in the hidden list */
  1167.         
  1168.         theMenu = GetHiddenMenu(paramPtr,titleStr);
  1169.         if (theMenu==NULL) 
  1170.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu to show");
  1171.         else {
  1172.                 /* get the before menu */
  1173.                 beforeMenuID = 0;
  1174.                 if (strcmp(beforeStr,"")!=0) {
  1175.                         beforeMenuID = GetMenuID(beforeStr);
  1176.                 }
  1177.                 /* move it from hidden to shown */
  1178.                 InsertMenu(theMenu,beforeMenuID);   
  1179.                 RemoveFromSaveList(paramPtr,theMenu);
  1180.                 DrawMenuBar();
  1181.         }
  1182.         for (i=1;i<paramPtr->paramCount;i++) 
  1183.                 HUnlock (paramPtr->params[i]);
  1184.         
  1185.         return;
  1186. }
  1187.  
  1188. /* insert an item into a menu */
  1189.  
  1190. pascal void InsertMenuItem(paramPtr)
  1191. XCmdBlockPtr    paramPtr;
  1192. {   
  1193.         int i,itsID,itemCount;
  1194.         Str255 titleStr,itemStr,afterStr;
  1195.         MenuHandle theMenu;
  1196.         int theMenuID;
  1197.         long afterItem;
  1198.         Ptr theItems;
  1199.         
  1200.         /* check paramter count */
  1201.         
  1202.         if (paramPtr->paramCount < 4) {
  1203.                 ResultIs(paramPtr,"Not enough parameters in Insert.");
  1204.                 return;
  1205.         }
  1206.         
  1207.         /* lock parameters down so we can point to them */
  1208.         
  1209.         for (i=1;i<4;i++) {
  1210.                 MoveHHi(paramPtr->params[i]);
  1211.                 HLock (paramPtr->params[i]);
  1212.         }
  1213.         
  1214.         /* get the parameters */
  1215.         
  1216.         strcpy(titleStr,*(paramPtr->params[1]));
  1217.         theItems = *(paramPtr->params[2]);
  1218.         strcpy(afterStr,*(paramPtr->params[3]));
  1219.         
  1220.         /* get the menu */
  1221.         
  1222.         theMenuID = GetMenuID(titleStr);
  1223.         if (theMenuID==NULL) {
  1224.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu for insert");
  1225.         }
  1226.         else {
  1227.                 /* get its handle */
  1228.                 theMenu = GetMHandle(theMenuID);
  1229.                 CtoPstr((char *)itemStr);
  1230.                 
  1231.                 /* Is it identified by name or number? */
  1232.                 
  1233.                 if (!isNumber(afterStr,&afterItem))
  1234.                         afterItem = ItemNumber(theMenu,afterStr);
  1235.                                 
  1236.                 /* add all items by inserting - so we aren't constrained to 255 char limit */
  1237.                 itemCount = NumHCItems(theItems);
  1238.                 for (i=0;i<itemCount;i++) {
  1239.                         GetHCItem(theItems,i+1,itemStr);
  1240.                         CtoPstr((char *)itemStr);
  1241.                         InsMenuItem(theMenu,itemStr,(int)(afterItem+i));
  1242.                 }
  1243.  
  1244.                 
  1245.                 /* register this change in the menu global */
  1246.                 
  1247.                 UpdateItemGlobal(paramPtr,titleStr);
  1248.         }
  1249.         for (i=1;i<4;i++) HUnlock (paramPtr->params[i]);
  1250.  
  1251. }
  1252.  
  1253. /* remove an item from a menu */
  1254.  
  1255. pascal void RemoveMenuItem(paramPtr)
  1256. XCmdBlockPtr    paramPtr;
  1257. {  
  1258.         int i,itsID;
  1259.         Str255 titleStr,itemStr;
  1260.         Ptr theTitle,theItems;
  1261.         MenuHandle theMenu;
  1262.         int theMenuID;
  1263.         long theItem;
  1264.         
  1265.         /* checkl parameter count */
  1266.         
  1267.         if (paramPtr->paramCount < 3) {
  1268.                 ResultIs(paramPtr,"Not enough parameters in Remove.");
  1269.                 return;
  1270.         }
  1271.  
  1272.         /* lock the parameters so we can point to them */
  1273.         
  1274.         for (i=1;i<3;i++) {
  1275.                 MoveHHi(paramPtr->params[i]);
  1276.                 HLock (paramPtr->params[i]);
  1277.         }
  1278.         
  1279.         /* get parameters */
  1280.         
  1281.         strcpy(titleStr,*(paramPtr->params[1]));
  1282.         strcpy(itemStr,*(paramPtr->params[2]));
  1283.         
  1284.         /* get the menu */
  1285.         
  1286.         theMenuID = GetMenuID(titleStr);
  1287.         if (theMenuID==NULL) 
  1288.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu for removal request");
  1289.         else {
  1290.                 /* get its handle */
  1291.                 
  1292.                 theMenu = GetMHandle(theMenuID);
  1293.                 
  1294.                 /* is it identified by name or number? */
  1295.                 if (!isNumber(itemStr,&theItem)) 
  1296.                         theItem = ItemNumber(theMenu,itemStr);
  1297.                         
  1298.             /* delete it and update the menu global */
  1299.             
  1300.                 DelMenuItem(theMenu,(int)theItem);
  1301.                 UpdateItemGlobal(paramPtr,titleStr);
  1302.                 
  1303.         }
  1304.         for (i=1;i<3;i++) HUnlock (paramPtr->params[i]);
  1305. }
  1306.  
  1307. /* enable an item in a menu */
  1308.  
  1309. pascal void EnableMenuItem(paramPtr)
  1310. XCmdBlockPtr    paramPtr;
  1311. {   
  1312.         int i,itsID;
  1313.         Str255 titleStr,itemStr;
  1314.         Ptr theTitle,theItems;
  1315.         MenuHandle theMenu;
  1316.         int theMenuID;
  1317.         long theItem;
  1318.         
  1319.         /* check parameter count */
  1320.         
  1321.         if (paramPtr->paramCount < 3) {
  1322.                 ResultIs(paramPtr,"Not enough parameters in Enable.");
  1323.                 return;
  1324.         }
  1325.         
  1326.         /* lock down parameters so we can point to them */
  1327.         
  1328.         for (i=1;i<3;i++) {
  1329.                 MoveHHi(paramPtr->params[i]);
  1330.                 HLock (paramPtr->params[i]);
  1331.         }
  1332.         
  1333.         /* get parameters */
  1334.         
  1335.         strcpy(titleStr,*(paramPtr->params[1]));
  1336.         strcpy(itemStr,*(paramPtr->params[2]));
  1337.         
  1338.         
  1339.         /* get the menu */
  1340.         
  1341.         theMenuID = GetMenuID(titleStr);
  1342.         
  1343.         if (theMenuID==NULL) 
  1344.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu for enable request");
  1345.         else {
  1346.         
  1347.                 /* get its handle */
  1348.                 
  1349.                 theMenu = GetMHandle(theMenuID);
  1350.                 
  1351.                 /* is it identified by name or number? */
  1352.                 
  1353.                 if (!isNumber(itemStr,&theItem)) {
  1354.                         theItem = ItemNumber(theMenu,itemStr);
  1355.                         if (theItem==0L) {  /* none to disable */
  1356.                                 ResultIs(paramPtr,"Invalid item number in enable");
  1357.                         
  1358.                                 for (i=1;i<3;i++) HUnlock (paramPtr->params[i]);
  1359.                                 return;
  1360.                         }
  1361.                 }
  1362.                 EnableItem(theMenu,(int)theItem);
  1363.                 
  1364.                 if ((int)theItem != 0) {
  1365.                 
  1366.                         /* update disable global */
  1367.                 
  1368.                         RemoveFromDisableGlobal(paramPtr,theMenu,(int)theItem);
  1369.                 }
  1370.                 else {   /* remove all items in it from the disable global */
  1371.                         for (i=0;i<CountMItems(theMenu);i++) {
  1372.                                         RemoveFromDisableGlobal(paramPtr,theMenu,(int)i+1);
  1373.                         }
  1374.                 }
  1375.         }
  1376.         for (i=1;i<3;i++) HUnlock (paramPtr->params[i]);
  1377. }
  1378.  
  1379. /* disable a menu item  */
  1380.  
  1381. pascal void DisableMenuItem(paramPtr)
  1382. XCmdBlockPtr    paramPtr;
  1383. {   
  1384.         int i,itsID;
  1385.         Str255 titleStr,itemStr;
  1386.         Ptr theTitle,theItems;
  1387.         MenuHandle theMenu;
  1388.         int theMenuID;
  1389.         long theItem;
  1390.         
  1391.         /* check parameter count */
  1392.         
  1393.         if (paramPtr->paramCount < 3) {
  1394.                 ResultIs(paramPtr,"Not enough parameters in Disable.");
  1395.                 return;
  1396.         }
  1397.         
  1398.         /* lock down parameters so we can point to them */
  1399.         
  1400.         for (i=1;i<3;i++) {
  1401.                 MoveHHi(paramPtr->params[i]);
  1402.                 HLock (paramPtr->params[i]);
  1403.         }
  1404.         
  1405.         /* get parameters */
  1406.         
  1407.         strcpy(titleStr,*(paramPtr->params[1]));
  1408.         strcpy(itemStr,*(paramPtr->params[2]));
  1409.         
  1410.         /* get the menu */
  1411.         
  1412.         theMenuID = GetMenuID(titleStr);
  1413.         
  1414.         if (theMenuID==NULL) 
  1415.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu for disable request");
  1416.         else {
  1417.                 /* get its handle */
  1418.                 theMenu = GetMHandle(theMenuID);
  1419.         
  1420.                 /* is it identified by name or number? */
  1421.                 
  1422.                 if (!isNumber(itemStr,&theItem)) {
  1423.                         theItem = ItemNumber(theMenu,itemStr);
  1424.         
  1425.                         if (theItem==0L) {  /* none to disable */
  1426.                                 ResultIs(paramPtr,"Invalid item number in disable");
  1427.                         
  1428.                                 for (i=1;i<3;i++) HUnlock (paramPtr->params[i]);
  1429.                         
  1430.                                 return;
  1431.                         }
  1432.                 }
  1433.  
  1434.                 /* disable it */
  1435.                 
  1436.                 DisableItem(theMenu,(int)theItem);
  1437.                 
  1438.                 
  1439.         
  1440.                 /* update the disabled menu global */
  1441.                 
  1442.                 if ((int)theItem != 0) {
  1443.         
  1444.                         AddToDisableGlobal(paramPtr,theMenu,(int)theItem);
  1445.                 }
  1446.                 else {
  1447.                         for (i=0;i<CountMItems(theMenu);i++) {
  1448.                                                 AddToDisableGlobal(paramPtr,theMenu,(int)i+1);
  1449.                         }
  1450.                 }
  1451.         }
  1452.  
  1453.         for (i=1;i<3;i++) HUnlock (paramPtr->params[i]);
  1454.                 
  1455. }
  1456.  
  1457. /* mark a menu item  */
  1458.  
  1459. pascal void MarkMenuItem(paramPtr)
  1460. XCmdBlockPtr    paramPtr;
  1461. {   
  1462.         int i,itsID;
  1463.         Str255 titleStr,itemStr,markStr;
  1464.         Ptr theTitle,theItems;
  1465.         MenuHandle theMenu;
  1466.         int theMenuID;
  1467.         long theItem;
  1468.         char markChar;
  1469.         
  1470.         /* checl parameter count */
  1471.         if (paramPtr->paramCount < 4) {
  1472.                 ResultIs(paramPtr,"Not enough parameters in Mark.");
  1473.                 return;
  1474.         }
  1475.         
  1476.         /* lock down the parameters so we can point to them */
  1477.         
  1478.         for (i=1;i<4;i++) {
  1479.                 MoveHHi(paramPtr->params[i]);
  1480.                 HLock (paramPtr->params[i]);
  1481.         }
  1482.         
  1483.         /* get parameters */
  1484.         
  1485.         strcpy(titleStr,*(paramPtr->params[1]));
  1486.         strcpy(itemStr,*(paramPtr->params[2]));
  1487.         
  1488.         /* get the menu */
  1489.         
  1490.         theMenuID = GetMenuID(titleStr);
  1491.         
  1492.         if (theMenuID==NULL) 
  1493.                 ResultIs(paramPtr,"MenuHandler error:Can't find menu for mark request");
  1494.         else {
  1495.                 /* get its handle */
  1496.                 theMenu = GetMHandle(theMenuID);
  1497.                 
  1498.                 /* is it identified by name or number? */
  1499.                 if (!isNumber(itemStr,&theItem)) {
  1500.                         theItem = ItemNumber(theMenu,itemStr);
  1501.                         if (theItem==0L) {  /* none to mark */
  1502.                                 ResultIs(paramPtr,"Invalid item number in mark");
  1503.                                 for (i=1;i<4;i++) HUnlock (paramPtr->params[i]);
  1504.                                 return;
  1505.                         }
  1506.                 }
  1507.                 
  1508.                 /* decode the mark parameter */
  1509.         strcpy(markStr,*(paramPtr->params[3]));
  1510.                 ucase(markStr);
  1511.                 if (strcmp(markStr,"NONE")==0) markChar = noMark;
  1512.                 else if (strcmp(markStr,"COMMAND")==0) markChar = commandMark;
  1513.                 else if (strcmp(markStr,"CHECK")==0) markChar = checkMark;
  1514.                 else if (strcmp(markStr,"DIAMOND")==0) markChar = diamondMark;
  1515.                 else if (strcmp(markStr,"APPLE")==0) markChar = appleMark;
  1516.                 else {
  1517.                         ResultIs(paramPtr,"Unknown mark type.");
  1518.                         return;
  1519.                 }
  1520.                 
  1521.                 /* set the mark */
  1522.                 
  1523.                 SetItemMark(theMenu,theItem,markChar);
  1524.                 
  1525.         }
  1526.  
  1527.         for (i=1;i<4;i++) HUnlock (paramPtr->params[i]);
  1528.                 
  1529. }
  1530.  
  1531. /* XCMD entry point */
  1532.  
  1533.  
  1534. pascal void main(paramPtr)
  1535. XCmdBlockPtr    paramPtr;
  1536. /* this is the entry point for the XFCN */
  1537. {
  1538.         Handle taskHandle,portHandle;
  1539.         Str255 temp;
  1540.         
  1541.         RememberA0();
  1542.         SetUpA4();              /* use global variables */
  1543.         
  1544.         /* get the opcode */
  1545.         if (paramPtr->paramCount==0) {
  1546.                 ResultIs(paramPtr,"No parameters in MenuHandler.");
  1547.                 RestoreA4();
  1548.                 return;
  1549.         }
  1550.         
  1551.         taskHandle = paramPtr->params[0];
  1552.         ucase(*taskHandle);
  1553.  
  1554.         /* branch on the opcode */
  1555.         if (strcmp(*taskHandle,"ADD")==0) AddAMenu(paramPtr);                   
  1556.         else if (strcmp(*taskHandle,"DELETE")==0) DeleteAMenu(paramPtr);                        
  1557.         else if (strcmp(*taskHandle,"HIDE")==0) HideMenu(paramPtr);                     
  1558.         else if (strcmp(*taskHandle,"SHOW")==0) ShowMenu(paramPtr); 
  1559.         else if (strcmp(*taskHandle,"INSERT")==0) InsertMenuItem(paramPtr);                     
  1560.         else if (strcmp(*taskHandle,"REMOVE")==0) RemoveMenuItem(paramPtr);                     
  1561.         else if (strcmp(*taskHandle,"ENABLE")==0) EnableMenuItem(paramPtr); 
  1562.         else if (strcmp(*taskHandle,"DISABLE")==0) DisableMenuItem(paramPtr); 
  1563.         else if (strcmp(*taskHandle,"MARK")==0) MarkMenuItem(paramPtr); 
  1564.         else {
  1565.                 strcpy(temp,"MenuHandler Error: unknown message ");
  1566.                 strcat(temp,*taskHandle);
  1567.                 ResultIs(paramPtr,temp);
  1568.         }
  1569.         RestoreA4();    
  1570.  
  1571.         return;
  1572. }
  1573.  
  1574.